package cadtoolbox.optimizer;

import java.util.Random;

import cadtoolbox.utils.Undoable;
import cadtoolbox.model.OligoGraph;

public abstract class Parameter <V,E> {

	public double currentValue;
	public double previousValue;
	public double minValue;
	public double maxValue;
	public String name="";
	public Object target;
	public boolean optimizable = true;
	
	
	/**
	 * Parameter abstract class for thermal annealing. Since there are many types of
	 * parameter possible, this is expected to be extended by anonymous classes.
	 * @param currentValue
	 * @param minValue
	 * @param maxValue
	 */
	public Parameter(double currentValue, double minValue, double maxValue, Object target){
		this.currentValue = currentValue;
		this.minValue = minValue;
		this.maxValue = maxValue;
		this.target = target;
		init();
	}
	
	//Init function to allow extending class to have additional initialization
	protected void init(){
		
	}
	
	public double gaussianPerturbation(Random rnd, double variance, OligoGraph<V,E> graph){
		this.previousValue = this.currentValue;
		this.currentValue = Math.max(minValue,Math.min(maxValue, variance*rnd.nextGaussian()+currentValue));
		updateTarget(graph);
		return this.currentValue;
	}
	
	public double externalModification(double newValue, OligoGraph<V,E> graph){
		this.previousValue = this.currentValue;
		this.currentValue = newValue;
		updateTarget(graph);
		return this.currentValue;
		}
	
	public void undo(OligoGraph<V,E> graph){
		this.currentValue = this.previousValue;
		updateTarget(graph);
		
	}
	
	protected abstract void updateTarget(OligoGraph<V,E> graph); // put currentValue in the target value, one way or another
	
	@Override
	public boolean equals(Object obj){
		if(obj.getClass() != Parameter.class){
			return false;
		}
		return ((Parameter) obj).target.equals(this.target);
	}
	
	public String toString(){
		return name;
	}
}
